package com.garlicts.framework.rpc;

import com.garlicts.framework.core.InstanceFactory;
import com.garlicts.framework.annotation.RpcService;
import com.garlicts.framework.common.*;
import com.garlicts.framework.core.BeanLoader;
import com.garlicts.framework.ioc.BeanContainerComponent;
import com.garlicts.framework.registry.ZookeeperServiceRegistry;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class RpcServer {

    private static final Logger LOGGER = LoggerFactory.getLogger(RpcServer.class);

    /**
     * 存放 服务名 与 服务对象 之间的映射关系
     */
    private Map<String, Object> handlerMap = new HashMap<String, Object>();

    private static final BeanLoader beanLoader = InstanceFactory.getBeanLoader();

    public RpcServer(){

    }

    public void start(){

        this.initHandlerMap();

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 创建并初始化 Netty 服务端 Bootstrap 对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup);
            bootstrap.channel(NioServerSocketChannel.class);
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel channel) throws Exception {
                    ChannelPipeline pipeline = channel.pipeline();
                    pipeline.addLast(new RpcDecoder(Request.class));
                    pipeline.addLast(new RpcEncoder(Response.class));
                    pipeline.addLast(new RpcServerHandler(handlerMap));
                }
            });
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            // 获取 RPC 服务器的 IP 地址与端口号
            String serviceAddress = IpUtil.getLocalIp();
            String[] addressArray = StringUtils.splitByWholeSeparator(serviceAddress, ":");
            String ip = addressArray[0];
            int port = Integer.parseInt(addressArray[1]);
            // 启动 RPC 服务器
            ChannelFuture channelFuture = bootstrap.bind(ip, port).sync();
            // 注册 RPC 服务地址
            new ZookeeperServiceRegistry().register(serviceAddress);
            LOGGER.info("register rpc server address: {}", serviceAddress);

            LOGGER.info("server started on port {}", port);
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

    public void initHandlerMap() {

        List<Class<?>> beanClassList = beanLoader.getBeanClassListByAnnotation(RpcService.class);
        if(CollectionUtils.isEmpty(beanClassList)) {
            return;
        }

        for(Class<?> clazz : beanClassList){
            try {
                RpcService gtsRpc = clazz.getAnnotation(RpcService.class);
                String serviceName = null;
                if(StringUtils.isBlank(gtsRpc.name())){
                    serviceName = clazz.getSimpleName();
                    StringUtils.replaceChars(serviceName, serviceName.substring(0, 1), serviceName.substring(0, 1).toLowerCase());
                }else{
                    serviceName = gtsRpc.name();
                }
                handlerMap.put(serviceName, BeanContainerComponent.getBean(clazz));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

}


